// C source file with the function definitions to handle TEXT files

// check_text_enc() function
// function to check the encoding of a text file
text_enc check_text_enc(char * text_file_path)
{
  // load the whole file in memory
  byte * ptr = load_file_mem(text_file_path);
  if (ptr == NULL)
    return TEXT_ENC_UNKNOWN;
  
  // variable to return
  text_enc rtn = TEXT_ENC_UNKNOWN;
  
  // otherwise check the encoding of the file
  umax file_size = get_file_size(text_file_path);
  // the first encoding check that does not give 
  // any errors is the one going to be selected
  // store the encoding before this one
  char_enc old_enc = CHAR_ARR_ENC_STATE;
  for (umax i = CHAR_ENC_ASCII; i < CHAR_ENC_END_INT; i++)
  {
    set_ch_arr_enc_state((char_enc) i);
    // iterate over the file data in ptr
    bool valid_enc = true;
    for (umax j = 0; j < file_size; /**/)
    {
      // check character size
      byte ch_size = chk_enc_ch(ptr + j, file_size - j);
      //~ printf("%llu %llu %llu\n", i, file_size, j);
      if (ch_size == 0) {
        valid_enc = false;
        break;
      }
      // advance to the next character
      j += ch_size;
    }
    // check if all encoded characters where 
    // valid to the encoding being used
    if (valid_enc) {
      rtn = (text_enc) i;
      break;
    }
  }
  
  // reset char array functions to old_enc
  set_ch_arr_enc_state(old_enc);
  // free memory used
  free_memory(ptr);
  return rtn;
}

// check_text_inc() function
// function to check if a text file is valid
text_err_cd check_text_inc(char * text_file_path)
{  
  // check params
  if (text_file_path == NULL)
    return TEXT_ERR_NULL_PATH;
  
  // check if the encoding is supported
  if (check_text_enc(text_file_path) != TEXT_ENC_UNKNOWN)
    return TEXT_ERR_NO_ERR;
  return TEXT_ERR_UNKNOWN_ENC;
}

// open_text_inc() function
// function to open an incomplete text structure
text * open_text_inc(char * text_file_path)
{  
  // check params
  text_err_cd err_cd_inc = check_text_inc(text_file_path);
  if (err_cd_inc > TEXT_ERR_LN)
    goto err;
  
  // pointer to return
  text * fptr = allocate_memory(sizeof(text), sizeof(byte));
  if (fptr == NULL)
    goto err;
  
  // fill the structure basics
  fptr -> PATH = text_file_path;
  fptr -> DATA = load_file_mem(text_file_path);
  fptr -> SIZE = get_file_size(text_file_path);
  fptr -> ENC = check_text_enc(text_file_path);
  fptr -> ERR_CD_INC = err_cd_inc;
  // TYPE, ST and ERR_CD_TP will have to be assigned 
  // by a specific text file type function
  
  // all good
  return fptr;
  
  // failure
  err:
  return NULL;
}

// close_text_inc() function
// function to close an incomplete text structure (free memory)
void close_text_inc(text * text_file)
{
  // verify text_file is not a NULL pointer
  if (text_file == NULL)
    return;
    
  // otherwise, free memory
  free_memory(text_file -> DATA);
  free_memory(text_file);
  return;
}

// print_text_start() function
// function to print the starting info of an incomplete text struct
void print_text_start(text * file)
{
  // check ptr
  if (file == NULL)
    return;
  
  // file info and error code
  printf("File: %s\n", file -> PATH);
  printf("File size (bytes): %llu\n", file -> SIZE);
  printf("FILE ERROR CODE (INC): %u\n", file -> ERR_CD_INC);
  printf("FILE ENCODING: %u\n\n", file -> ENC);
  
  // print file contents (can be awful for big text files)
  printf("########## Text file contents start ##########\n\n");
  set_ch_arr_enc_state(file -> ENC);
  print_chenc_arr(file -> DATA, file -> SIZE, file -> ENC);
  printf("\n########## Text file contents end ##########\n");
  
  // done, reset char encoding funcs
  set_ch_arr_enc_state(CHAR_ENC_ASCII);
  return;
}

// print_text_inc() function
// function to print the information of an incomplete text structure
void print_text_inc(text * file)
{
  // check ptr
  if (file == NULL)
    return;
  
  // starting visual queue
  printf("\n### Text incomplete struct info start ###\n\n");
  
  // print the start of the text struct
  print_text_start(file);
  
  // end of structure
  printf("\n### Text incomplete struct info end ###\n");  
  return;
}

// insert_text_chars() function
// function to insert chints from a chint array into txt_f object at txt_pos
bool insert_text_chars(text * txt_f, void * txt_pos, umax * chints, umax csize)
{
  // check params
  if (txt_f == NULL || txt_pos == NULL || chints == NULL || csize == 0)
    goto err;
  
  // insert the bytes
  void * ptr = insert_chints_in_chenc_arr(txt_f -> DATA, txt_f -> SIZE, txt_f -> ENC, txt_pos, chints, csize);
  if (ptr == NULL)
    goto err;
  
  // if everything went nice update txt_f
  txt_f -> DATA = ptr;
  txt_f -> SIZE = txt_f -> SIZE + csize;
  return true;  
  err: // error
  return false;
}

// remove_text_chars() function
// function to remove characters from a txt_f object at txt_pos
bool remove_text_chars(text * txt_f, void * txt_pos, umax rm_size)
{
  // check params
  if (txt_f == NULL || txt_pos == NULL || rm_size == 0)
    goto err;
  
  // remove the characters
  umax result = remove_chencs_in_chenc_arr(txt_f -> DATA, txt_f -> SIZE, txt_f -> ENC, txt_pos, rm_size);
  if (result == 0)
    goto err;
  
  // update txt_f
  txt_f -> SIZE = txt_f -> SIZE - rm_size;  
  // all went good
  return true;
  err: // error
  return false;
}
